package com.ssyt.examinationsystem.controller;

import com.alibaba.fastjson.JSON;
import com.ssyt.examinationsystem.dto.PaperDto;
import com.ssyt.examinationsystem.entity.*;
import com.ssyt.examinationsystem.service.*;
import com.ssyt.examinationsystem.service.impl.*;
import com.ssyt.examinationsystem.util.CollectionUtils;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Servlet implementation class ExamController
 */
public class ExamController extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public ExamController() {
        super();
        // TODO Auto-generated constructor stub
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
     * response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        doPost(request, response);
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
     * response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 获取flag值
        String flag = request.getParameter("flag");

        // 创建安排考试业务对象
        IArrangeInfoService arrangeService = new ArrangeInfoServiceImpl();
        ICourseInfoService courseService = new CourseInfoServiceImpl();
        IExamService examService = new ExamServiceImpl();

        //
        PrintWriter out = response.getWriter();

        if ("start_exam".equals(flag)) {
            startExam(request, response, arrangeService, out);
        } else if ("exam".equals(flag)) {

            IPaperInfoService paperService = new PaperInfoServiceImpl();
            exam(request, response, paperService);
        } else if ("start".equals(flag)) {
            start(courseService, request, response);
        } else if ("submit_paper".equals(flag)) {
            submitPaper(out, request, response, arrangeService, examService);
        }

        out.flush();
        out.close();
    }

    private void submitPaper(PrintWriter out, HttpServletRequest request, HttpServletResponse response,
                             IArrangeInfoService arrangeService, IExamService examService) {
        // 创建一个PaperServiceImpl对象
        IPaperInfoService paperService = new PaperInfoServiceImpl();
        // 创建一个成绩业务对象
        IScoreInfoService scoreService = new ScoreInfoServiceImpl();
        // 创建一个主观答案业务对象
        ISubAnswerInfoService subAnService = new SubAnswerInfoServiceImpl();

        // 获取学生的Id
        String stuId = String.valueOf(request.getSession().getAttribute("stuId"));

        // 获取页面传入paperId
        String paperId = request.getParameter("paperId");

        PaperDto paperDto = paperService.getPaperInfoById(paperId);

        String testId = String.valueOf(paperDto.getPaper().get("testId"));
        int row1 = 0;
        // 通过组卷类型计算分数
        if ("1".equals(testId)) { // 手动
            // 通过规则编号获取规则信息
            Map<String, Object> rule = paperDto.getRule();
            ////////////////////////// 单选题 /////////////////////////
            String scIds = String.valueOf(rule.get("scIds"));

            List<ManualEntity> manualList = JSON.parseArray(scIds, ManualEntity.class);
            // 计算单选题的分数
            float singleTotalScore = 0;

            // 获取该试卷对应单选题的题号
            String[] singleIds = request.getParameterValues("single");
            // 把所有的编号使用","连接
            StringBuffer sb = new StringBuffer();

            for (String value : singleIds) {
                sb.append(value + ",");
            }

            String ids = sb.substring(0, sb.length() - 1);

            // 获取所有当选题对应正确答案
            List<String> singleCorrectAnswerList = examService.getAnswersByIds(ids, "choiceInfo", "choiceId");

            for (int i = 0; i < singleIds.length; i++) {
                // 获取学生单选题作答答案
                String stuAnswer = request.getParameter("single" + singleIds[i]);
                // 获取当前题正确答案
                String answer = singleCorrectAnswerList.get(i);

                if (answer.equals(stuAnswer)) {
                    singleTotalScore = singleTotalScore + Float.valueOf(manualList.get(i).getScore());
                }
            }
            ////////////////////// 多选题 ////////////////////
            String mulIds = String.valueOf(rule.get("mulIds"));
            manualList = JSON.parseArray(mulIds, ManualEntity.class);
            // 计算单选题的分数
            float multipleTotalScore = 0;
            // 获取该试卷对应单选题的题号
            String[] multipleIds = request.getParameterValues("multiple");
            // 把所有的编号使用","连接
            sb = new StringBuffer();

            for (String value : multipleIds) {
                sb.append(value + ",");
            }

            ids = sb.substring(0, sb.length() - 1);

            // 获取所有当选题对应正确答案
            List<String> multipleCorrectAnswerList = examService.getAnswersByIds(ids, "choiceInfo", "choiceId");

            for (int i = 0; i < multipleIds.length; i++) {
                // 获取学生单选题作答答案
                String stuAnswer = "";
                String[] mulAnswer = request.getParameterValues("multiple" + multipleIds[i]);
                if (mulAnswer != null) {
                    for (String value : mulAnswer) {
                        stuAnswer += value;
                    }
                }

                // 获取当前题正确答案
                String answer = multipleCorrectAnswerList.get(i);

                if (answer.equals(stuAnswer)) {
                    multipleTotalScore = multipleTotalScore + Float.valueOf(manualList.get(i).getScore());
                }
            }

            ////////////////////////// 填空题 /////////////////////////

            String bkIds = String.valueOf(rule.get("bkIds"));
            manualList = JSON.parseArray(bkIds, ManualEntity.class);
            // 计算填空题的分数
            float blankTotalScore = 0;
            // 获取该试卷对应填空题的题号
            String[] blankIds = request.getParameterValues("blank");
            // 把所有的编号使用","连接
            sb = new StringBuffer();

            for (String value : blankIds) {
                sb.append(value + ",");
            }

            ids = sb.substring(0, sb.length() - 1);

            // 获取所有填空题对应正确答案
            List<String> blankCorrectAnswerList = examService.getAnswersByIds(ids, "blankInfo", "blankId");

            for (int i = 0; i < blankIds.length; i++) {
                // 获取学生填空题作答答案
                String stuAnswer = request.getParameter("blank" + blankIds[i]);
                // 获取当前题正确答案
                String answer = blankCorrectAnswerList.get(i);

                if (answer.equals(stuAnswer)) {
                    blankTotalScore = blankTotalScore + Float.valueOf(manualList.get(i).getScore());
                }
            }

            ////////////////////////// 判断题 /////////////////////////
            String jdIds = String.valueOf(rule.get("jdIds"));
            manualList = JSON.parseArray(jdIds, ManualEntity.class);

            // 计算单选题的分数
            float judgeTotalScore = 0;
            // 获取该试卷对应判断题的题号
            String[] judgeIds = request.getParameterValues("judge");
            // 把所有的编号使用","连接
            sb = new StringBuffer();

            for (String value : judgeIds) {
                sb.append(value + ",");
            }

            ids = sb.substring(0, sb.length() - 1);

            // 获取所有判断题对应正确答案
            List<String> judgeCorrectAnswerList = examService.getAnswersByIds(ids, "judgeInfo", "judgeId");

            for (int i = 0; i < judgeIds.length; i++) {
                // 获取学生判断题作答答案
                String stuAnswer = request.getParameter("judge" + judgeIds[i]);
                // 获取当前题正确答案
                String answer = judgeCorrectAnswerList.get(i);
                answer = answer.substring(0, 1);

                if (answer.equals(stuAnswer)) {
                    judgeTotalScore = judgeTotalScore + Float.valueOf(manualList.get(i).getScore());
                }
            }

            float objectiveScore = singleTotalScore + blankTotalScore + multipleTotalScore + judgeTotalScore;
            // 创建一个成绩对象
            ScoreInfo score = new ScoreInfo();
            PaperInfo paper = new PaperInfo();
            paper.setPaperId(Integer.valueOf(paperId));
            score.setPaper(paper);
            StudentInfo stu = new StudentInfo();
            stu.setStuId(Integer.valueOf(stuId));
            score.setStu(stu);
            score.setObjectiveScore(objectiveScore);
            // 调用添加成绩的业务方法
            row1 = scoreService.addScore(score);

        } else { // 随机
            // 通过规则编号获取规则信息
            Map<String, Object> rule = paperDto.getRule();
            ////////////////// 计算每种客观题型的每题分数
            float scScore = Float.valueOf(String.valueOf(rule.get("scScore")))
                    / Integer.valueOf(String.valueOf(rule.get("scNumber")));
            float mulScore = Float.valueOf(String.valueOf(rule.get("mulScore")))
                    / Integer.valueOf(String.valueOf(rule.get("mulNumber")));
            float bkScore = Float.valueOf(String.valueOf(rule.get("bkScore")))
                    / Integer.valueOf(String.valueOf(rule.get("bkNumber")));
            float jdScore = Float.valueOf(String.valueOf(rule.get("jdScore")))
                    / Integer.valueOf(String.valueOf(rule.get("jdNumber")));

            // 定义不同题型正确提数
            int scNumber = 0;
            int mulNumber = 0;
            int bkNumber = 0;
            int jdNumber = 0;

            ////////////////////////// 单选题 /////////////////////////
            // 获取该试卷对应单选题的题号
            String[] singleIds = request.getParameterValues("single");
            // 把所有的编号使用","连接
            StringBuffer sb = new StringBuffer();

            for (String value : singleIds) {
                sb.append(value + ",");
            }

            String ids = sb.substring(0, sb.length() - 1);

            // 获取所有当选题对应正确答案
            List<String> singleCorrectAnswerList = examService.getAnswersByIds(ids, "choiceInfo", "choiceId");

            for (int i = 0; i < singleIds.length; i++) {
                // 获取学生单选题作答答案
                String stuAnswer = request.getParameter("single" + singleIds[i]);
                // 获取当前题正确答案
                String answer = singleCorrectAnswerList.get(i);

                if (answer.equals(stuAnswer)) {
                    scNumber++;
                }
            }

            // 计算单选题的分数
            float singleTotalScore = scNumber * scScore;

            ////////////////////// 多选题 ////////////////////
            // 获取该试卷对应单选题的题号
            String[] multipleIds = request.getParameterValues("multiple");
            // 把所有的编号使用","连接
            sb = new StringBuffer();

            for (String value : multipleIds) {
                sb.append(value + ",");
            }

            ids = sb.substring(0, sb.length() - 1);

            // 获取所有当选题对应正确答案
            List<String> multipleCorrectAnswerList = examService.getAnswersByIds(ids, "choiceInfo", "choiceId");

            for (int i = 0; i < multipleIds.length; i++) {
                // 获取学生单选题作答答案
                String stuAnswer = "";
                String[] mulAnswer = request.getParameterValues("multiple" + multipleIds[i]);
                if (mulAnswer != null) {
                    for (String value : mulAnswer) {
                        stuAnswer += value;
                    }
                }

                // 获取当前题正确答案
                String answer = multipleCorrectAnswerList.get(i);

                if (answer.equals(stuAnswer)) {
                    mulNumber++;
                }
            }

            // 计算单选题的分数
            float multipleTotalScore = mulNumber * mulScore;

            ////////////////////////// 填空题 /////////////////////////
            // 获取该试卷对应填空题的题号
            String[] blankIds = request.getParameterValues("blank");
            // 把所有的编号使用","连接
            sb = new StringBuffer();

            for (String value : blankIds) {
                sb.append(value + ",");
            }

            ids = sb.substring(0, sb.length() - 1);

            // 获取所有填空题对应正确答案
            List<String> blankCorrectAnswerList = examService.getAnswersByIds(ids, "blankInfo", "blankId");

            for (int i = 0; i < blankIds.length; i++) {
                // 获取学生填空题作答答案
                String stuAnswer = request.getParameter("blank" + blankIds[i]);
                // 获取当前题正确答案
                String answer = blankCorrectAnswerList.get(i);

                if (answer.equals(stuAnswer)) {
                    bkNumber++;
                }
            }

            // 计算填空题的分数
            float blankTotalScore = bkNumber * bkScore;

            ////////////////////////// 判断题 /////////////////////////
            // 获取该试卷对应判断题的题号
            String[] judgeIds = request.getParameterValues("judge");
            // 把所有的编号使用","连接
            sb = new StringBuffer();

            for (String value : judgeIds) {
                sb.append(value + ",");
            }

            ids = sb.substring(0, sb.length() - 1);

            // 获取所有判断题对应正确答案
            List<String> judgeCorrectAnswerList = examService.getAnswersByIds(ids, "judgeInfo", "judgeId");

            for (int i = 0; i < judgeIds.length; i++) {
                // 获取学生判断题作答答案
                String stuAnswer = request.getParameter("judge" + judgeIds[i]);
                // 获取当前题正确答案
                String answer = judgeCorrectAnswerList.get(i);
                answer = answer.substring(0, 1);

                if (answer.equals(stuAnswer)) {
                    jdNumber++;
                }
            }

            // 计算单选题的分数
            float judgeTotalScore = jdNumber * jdScore;

            float objectiveScore = singleTotalScore + blankTotalScore + multipleTotalScore + judgeTotalScore;
            // 创建一个成绩对象
            ScoreInfo score = new ScoreInfo();
            PaperInfo paper = new PaperInfo();
            paper.setPaperId(Integer.valueOf(paperId));
            score.setPaper(paper);
            StudentInfo stu = new StudentInfo();
            stu.setStuId(Integer.valueOf(stuId));
            score.setStu(stu);
            score.setObjectiveScore(objectiveScore);
            // 调用添加成绩的业务方法
            row1 = scoreService.addScore(score);

        }
        ///////////////////// 将主观题答案放到主观题答题表中//////////////////
        String[] subjectiveIds = request.getParameterValues("subjective");

        // 把所有的编号使用","连接
        StringBuffer sb = new StringBuffer();

        for (String value : subjectiveIds) {
            sb.append(value + "-");
        }

        String ids = sb.substring(0, sb.length() - 1);

        String subAnswers = "";
        // 获取所有判断题对应正确答案
        List<String> subCorrectAnswerList = new ArrayList<String>();

        for (int i = 0; i < subjectiveIds.length; i++) {
            // 获取学生判断题作答答案
            String stuAnswer = request.getParameter("subjective" + subjectiveIds[i]);
            subCorrectAnswerList.add(stuAnswer);
        }

        if (CollectionUtils.isEmptyForList(subCorrectAnswerList)) {
            for (String string : subCorrectAnswerList) {
                subAnswers = subAnswers + string + "-";
            }
        }
        subAnswers = subAnswers.substring(0, subAnswers.length() - 1);

        SubjectiveAnswerInfo subAnswer = new SubjectiveAnswerInfo();

        PaperInfo paper = new PaperInfo();
        paper.setPaperId(Integer.valueOf(paperId));
        subAnswer.setPaper(paper);
        StudentInfo stu = new StudentInfo();
        stu.setStuId(Integer.valueOf(stuId));
        subAnswer.setStu(stu);
        subAnswer.setAnswer(subAnswers);
        subAnswer.setIds(ids);

        int row2 = subAnService.addSubAnswer(subAnswer);

        if (row1 > 0 && row2 > 0) {
            out.print("ok");
        }

    }

    /**
     * 转发到开始考试页面
     *
     * @param ruleService
     * @param request
     * @param response
     * @throws IOException
     * @throws ServletException
     */
    private void start(ICourseInfoService courseService, HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 获取所有科目
        List<CourseInfo> courseList = courseService.getCourseInfos();
        request.setAttribute("courseList", courseList);
        request.getRequestDispatcher("WEB-INF/views/exam/startExam.jsp").forward(request, response);
    }

    /**
     * 生成考试试卷的方法
     *
     * @param request
     * @param response
     * @param paperService
     * @throws IOException
     * @throws ServletException
     */
    private void exam(HttpServletRequest request, HttpServletResponse response, IPaperInfoService paperService)
            throws ServletException, IOException {
        String paperId = request.getParameter("paperId");
        PaperDto dto = paperService.getPaperInfoById(paperId);
        request.setAttribute("dto", dto);

        request.getRequestDispatcher("WEB-INF/views/exam/exam.jsp").forward(request, response);
    }

    /**
     * 开始考试
     *
     * @param request
     * @param response
     * @param studentService
     * @param arrangeService
     * @param out
     */
    private void startExam(HttpServletRequest request, HttpServletResponse response, IArrangeInfoService arrangeService,
                           PrintWriter out) {
        // 通过session学号
        String stuId = String.valueOf(request.getSession().getAttribute("stuId"));

        // 获取课程编号
        String courseId = request.getParameter("courseId");
        // 获取安排的试卷编号
        String paperId = arrangeService.startExam(stuId, courseId);

        if (paperId == null) {
            out.print("no");
        } else {
            out.print(paperId);
        }
    }

}
